package com.demo.woziqi.util;

import com.demo.woziqi.dao.UserDAO;
import com.demo.woziqi.entity.Chess;
import com.demo.woziqi.entity.User;
import com.demo.woziqi.message.Message;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import java.io.*;
import java.net.Socket;
import java.util.*;

/**
 * @Author 宋明松
 * @Version V1.0.0
 * @Date 2022-05-20
 */
public class GameUtil {
    private static GameConstant gamePanel = new GameConstant();
    public static List<Chess> list = new ArrayList<>();
    public static int chessNum = 0; // 记录打印棋子的数量

    /**
     * 写文件
     *
     * @param file
     * @return
     */
    private static boolean writeFile(File file) {
        if (file == null) {
            return false;
        }
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(GameConstant.chess);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 读文件
     *
     * @param file
     */
    public static boolean readFile(File file) { // 反序列化，将文件中的对象读取到内存中
        if (file == null) {
            return false;
        }
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(file));
            list = (List<Chess>) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * 保存棋谱，并提示保存结果信息
     */
    public static void isWriteFile(Stage stage) { // 保存棋谱弹出窗口，是否保存成功
        FileChooser fileChooser = new FileChooser(); // 创建弹出窗口
        File file = fileChooser.showSaveDialog(stage); // 弹出保存文件窗口
        if (file == null) { // 点击取消时：file为null，中断执行
            return;
        }
        if (GameUtil.writeFile(file)) {
            Alert a = new Alert(Alert.AlertType.INFORMATION);
            a.setHeaderText("棋谱保存成功");
            a.setContentText("路径：" + file.toString());
            a.show();
        } else {
            Alert a = new Alert(Alert.AlertType.ERROR);
            a.setHeaderText("棋谱保存失败");
            a.show();
        }
    }

    /**
     * 添加棋子方法
     *
     * @param black 棋子颜色
     * @param b     当前棋子下载顺序，false（更改为白棋）true（更改为黑棋）
     */
    public static void setChess(Color black, boolean b, Pane pane) { // 添加棋子
        Circle circleBlack = new Circle(GameUtil.list.get(chessNum).getxIndex() * gamePanel.LINE_DISTANCE + gamePanel.MARGIN, GameUtil.list.get(chessNum).getyIndex() * gamePanel.LINE_DISTANCE + gamePanel.MARGIN, 20, black); // 传入时需要转换为坐标
        Chess blackChess = new Chess(GameUtil.list.get(chessNum).getxIndex(), GameUtil.list.get(chessNum).getyIndex(), GameUtil.list.get(chessNum).getColor());//创建黑棋
        GameConstant.chess.add(blackChess); // 添加棋子
        pane.getChildren().add(circleBlack); // 将黑棋添加到棋盘中
        GameConstant.flag = b; // 更改下棋顺序
    }

    /**
     * 删除棋子方法（悔棋）
     */
    public static void regretChess(Pane pane) { // 悔棋
        if (GameConstant.chess.size() == 0) { // 面板上棋子悔完，不执行
            return;
        }
        pane.getChildren().remove(pane.getChildren().size() - 1);// 移除面板上的最后一枚棋子
        GameConstant.chess.remove(GameConstant.chess.size() - 1); // 移除最后一枚棋子
        GameConstant.flag = !GameConstant.flag;//棋子颜色取反
        if (GameConstant.isEnd) { // 对局结束，更改为对局未结束
            GameConstant.isEnd = false;
        }
    }

    /**
     * 判断胜负方法
     *
     * @param chess 棋子对象
     * @return 返回 1 存在 ，2 和棋，0 不存在
     */
    public static int isWin(Chess chess) { // 判断胜负
        int nums = 0; //连子数
        // 1,判断垂直方向上是否能判断出胜负
        // 2,以当前的chess坐标为起点，分别向上下两个方法进行判断，判断是否有同色的棋子
        // 向下找同色棋子
        for (int i = chess.getyIndex() + 1; i <= chess.getyIndex() + 4; i++) {
            if (isExit(chess.getxIndex(), i, chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        // 向上找同色棋子
        for (int i = chess.getyIndex() - 1; i >= chess.getyIndex() - 4; i--) {
            if (isExit(chess.getxIndex(), i, chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        // 1,判断水平方向上是否能判断出胜负
        // 2,以当前的chess坐标为起点，分别向左右两个方法进行判断，判断是否有同色的棋子
        // 向右找同色棋子
        nums = 0;
        for (int i = chess.getxIndex() + 1; i <= chess.getxIndex() + 4; i++) {
            if (isExit(i, chess.getyIndex(), chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        // 向左找同色棋子
        for (int i = chess.getxIndex() - 1; i >= chess.getxIndex() - 4; i--) {
            if (isExit(i, chess.getyIndex(), chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        nums = 0;
        // 向右上找同色棋子
        int j = chess.getyIndex();
        for (int i = chess.getxIndex() + 1; i <= chess.getxIndex() + 4; i++) {
            if (isExit(i, --j, chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        // 向右下找同色棋子
        int j2 = chess.getyIndex();
        for (int i = chess.getxIndex() - 1; i >= chess.getxIndex() - 4; i--) {
            if (isExit(i, ++j2, chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        // 向左上找同色棋子
        nums = 0;
        int j3 = chess.getyIndex();
        for (int i = chess.getxIndex() - 1; i >= chess.getxIndex() - 4; i--) {
            if (isExit(i, --j3, chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        // 向左下找同色棋子
        int j4 = chess.getyIndex();
        for (int i = chess.getxIndex() + 1; i <= chess.getxIndex() + 4; i++) {
            if (isExit(i, ++j4, chess.getColor())) {
                nums++;
            } else {
                break;
            }
        }
        if (nums >= 4) {
            return 1;
        }
        //判断和棋
        if (GameConstant.chess.size() == GameConstant.LINE_NUM * GameConstant.LINE_NUM) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setHeaderText("和棋");
            alert.show();
            return 2;
        }
        return 0;
    }

    /**
     * 遍历数组查看该颜色的棋子是否存在
     *
     * @param x     需要判断点的x坐标(棋谱中的坐标）
     * @param y     需要判断点的y坐标(棋谱中的坐标）
     * @param color 需要判断点的颜色，0黑色，1白色
     * @return 返回true表示存在
     */
    public static boolean isExit(int x, int y, int color) {
        for (int i = 0; i < GameConstant.chess.size(); i++) {
            if (GameConstant.chess.get(i).getxIndex() == x && GameConstant.chess.get(i).getyIndex() == y && GameConstant.chess.get(i).getColor() == color) {
                return true;
            }
        }
        return false;
    }

    /**
     * 遍历数组查看该颜色的棋子是否存在，不区分颜色
     *
     * @param x 需要判断点的x坐标(棋谱中的坐标）
     * @param y 需要判断点的y坐标(棋谱中的坐标）
     * @return 返回true表示存在
     */
    public static boolean isExitAll(int x, int y) {
        for (int i = 0; i < GameConstant.chess.size(); i++) {
            if (GameConstant.chess.get(i).getxIndex() == x && GameConstant.chess.get(i).getyIndex() == y) {
                return true;
            }
        }
        return false;
    }

    /**
     * 客户端 发送消息方法
     * @param msg 需要发送的消息
     * @return 返回true表示成功，false表示失败
     */
    public static boolean sendMessage(Message msg) {
        try (Socket socket = new Socket(GameConstant.DIpText, GameConstant.DDkText)) {
            OutputStream os = socket.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(msg); // 将需要发送的消息封装，发送message类
        } catch (Exception e) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("提醒");
            alert.setHeaderText("对方未上线");
            alert.show();
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 是否重开一局
     * @return 返回true表示同意
     */
    public static boolean isAgree() {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setHeaderText("对方要求重开一局，是否同意？");
        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == ButtonType.OK) { // 点击确定执行
            return GameConstant.isAgree =true;
        }
        return GameConstant.isAgree =false;
    }

    /**
     *是否同意悔棋
     * @return 返回true表示同意
     */
    public static boolean isAgreeRegret() {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setHeaderText("对方要求悔棋，是否同意？");
        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == ButtonType.OK) { // 点击确定执行
            return GameConstant.isAgreeRegret =true;
        }
        return GameConstant.isAgreeRegret =false;
    }
}
